package com.eian.boot.rabbit.model;

import com.eian.boot.common.id.IdHelper;
import com.eian.boot.rabbit.common.constant.RetryConfig;
import com.eian.boot.rabbit.util.TraceIdUtil;
import com.fasterxml.jackson.annotation.JsonInclude;

import java.io.Serializable;
import java.time.Instant;

@JsonInclude(JsonInclude.Include.NON_NULL)
public record Message<T>(
        /* 消息ID */
        String messageId,
        /* 消息时间 */
        long timestamp,
        /* 链路ID */
        String traceId,
        /* 消息来源 */
        String source,
        /* 消息内容 */
        T payload,
        /* 重试次数 */
        Integer retryCount,
        /* 最大重试次数 */
        Integer maxRetry,
        /* 延迟时间，在使用延迟队列时为必填项 */
        Long deliveryTime
) implements Serializable {

    public Message(T payload) {
        this(
                IdHelper.simpleUuid(),
                Instant.now().toEpochMilli(),
                TraceIdUtil.getTraceId(),
                null,
                payload,
                0,
                RetryConfig.DEFAULT_MAX_ATTEMPTS,
                null
        );
    }

    public Message<T> withSource(String source) {
        return new Message<>(
                this.messageId,
                this.timestamp,
                this.traceId,
                source,
                this.payload,
                this.retryCount,
                this.maxRetry,
                this.deliveryTime
        );
    }

    public Message<T> withMaxRetry(int maxRetry) {
        return new Message<>(
                this.messageId,
                this.timestamp,
                this.traceId,
                this.source,
                this.payload,
                this.retryCount,
                maxRetry,
                this.deliveryTime
        );
    }

    public Message<T> withDeliveryTime(long deliveryTime) {
        return new Message<>(
                this.messageId,
                this.timestamp,
                this.traceId,
                this.source,
                this.payload,
                this.retryCount,
                this.maxRetry,
                deliveryTime
        );
    }

    public Message<T> incrementRetryCount() {
        return new Message<>(
                this.messageId,
                this.timestamp,
                this.traceId,
                this.source,
                this.payload,
                this.retryCount != null ? this.retryCount + 1 : 1,
                this.maxRetry,
                this.deliveryTime
        );
    }
}